package com.zychowaniec.opengl;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;

import com.zychowaniec.shapes.Triangle;

public class OGLRenderer implements Renderer {
	private Context mContext;
	private FloatBuffer mVertexBuffer = null;
	private FloatBuffer mColorBuffer = null;
	private ShortBuffer mTriangleBorderIndicesBuffer = null;
	private int mNumOfTriangleBorderIndices = 0;

	public float mAngleX = 0.0f;
	public float mAngleY = 0.0f;
	public float mAngleZ = 0.0f;
	private float mPreviousX;
	private float mPreviousY;
	private final float TOUCH_SCALE_FACTOR = 0.6f;

	public OGLRenderer(Context context) {
		mContext = context;
	}

	Triangle mTriangle = new Triangle();

	public void onDrawFrame(GL10 gl) {
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		gl.glClearColor(0.2f, 0.2f, 0.2f, 1.0f);

		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		gl.glTranslatef(0.0f, 0.0f, -3.0f);
		gl.glRotatef(mAngleX, 1, 0, 0);
		gl.glRotatef(mAngleY, 0, 1, 0);
		gl.glRotatef(mAngleZ, 0, 0, 1);
		gl.glPushMatrix();
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);

		gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
		gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);

		// Set line color to green gl.glColor4f(0.0f, 1.0f, 0.0f, 0.2f);

		// Draw all lines
		gl.glDrawElements(GL10.GL_LINES, mNumOfTriangleBorderIndices,
				GL10.GL_UNSIGNED_SHORT, mTriangleBorderIndicesBuffer);
		gl.glPopMatrix();

		gl.glPushMatrix();
		gl.glRotatef(-mAngleX, 1, 1, 1);
		gl.glRotatef(-mAngleY, 0, 1, 0);
		gl.glRotatef(-mAngleZ, 0, 0, 1);

		mTriangle.draw(gl);
		// GLU.gluLookAt(gl, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX,
		// upY, upZ)
	}

	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
		gl.glEnable(GL10.GL_DEPTH_TEST);

		// Get all the buffers ready
		setAllBuffers();

	}

	public void onSurfaceChanged(GL10 gl, int width, int height) {
		gl.glViewport(0, 0, width, height);
		float aspect = (float) width / height;
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glFrustumf(-aspect, aspect, -1.0f, 1.0f, 1.0f, 10.0f);
	}

	private void setAllBuffers() {
		// Set vertex buffer
		float vertexlist[] = { -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f,
				0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, };

		float colorlist[] = { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f,
				1.0f, 0.7f, 0.0f, 1.0f, 1.0f, 0.8f, 0.0f, 0.5f, 0.0f, 1.0f,
				0.0f, 1.0f };

		ByteBuffer vbb = ByteBuffer.allocateDirect(vertexlist.length * 4);
		vbb.order(ByteOrder.nativeOrder());
		mVertexBuffer = vbb.asFloatBuffer();
		mVertexBuffer.put(vertexlist);
		mVertexBuffer.position(0);

		ByteBuffer vbb2 = ByteBuffer.allocateDirect(colorlist.length * 4);
		vbb2.order(ByteOrder.nativeOrder());
		mColorBuffer = vbb2.asFloatBuffer();
		mColorBuffer.put(colorlist);
		mColorBuffer.position(0);

		// Set triangle border buffer with vertex indices
		short trigborderindexlist[] = { 4, 0, 4, 1, 4, 2, 4, 3, 0, 1, 1, 3, 3,
				2, 2, 0, 0, 3 };
		mNumOfTriangleBorderIndices = trigborderindexlist.length;
		ByteBuffer tbibb = ByteBuffer
				.allocateDirect(trigborderindexlist.length * 2);
		tbibb.order(ByteOrder.nativeOrder());
		mTriangleBorderIndicesBuffer = tbibb.asShortBuffer();
		mTriangleBorderIndicesBuffer.put(trigborderindexlist);
		mTriangleBorderIndicesBuffer.position(0);
	}

	boolean active = false;

	public boolean onTouchEvent(MotionEvent e) {
		float x = e.getX();
		float y = e.getY();
		switch (e.getAction()) {

		case MotionEvent.ACTION_DOWN:
			active = true;
			break;
		case MotionEvent.ACTION_UP:
			active = false;
			break;

		case MotionEvent.ACTION_MOVE:
			if (active) {
				float dx = x - mPreviousX;
				float dy = y - mPreviousY;
				mAngleY = (mAngleY + (int) (dx * TOUCH_SCALE_FACTOR) + 360) % 360;
				mAngleX = (mAngleX + (int) (dy * TOUCH_SCALE_FACTOR) + 360) % 360;
			}
			break;

		}
		mPreviousX = x;
		mPreviousY = y;

		return true;
	}
}
